package com.lingyue.cpd.test.lock;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author deep.wu
 * @version 1.0 on 2020-04-21 00:16.
 */
@Slf4j
public class ReentrantLockTest3 {

    /**
     * 响应中断
     * 响应中断就是一个线程获取不到锁，不会傻傻的一直等下去，ReentrantLock会给予一个中断回应。
     * 在这里我们举一个死锁的案例。
     * 定义了两个锁lock1和lock2。然后使用两个线程thread和thread1构造死锁场景。
     * 正常情况下，这两个线程相互等待获取资源而处于死循环状态。
     * 但是我们此时thread中断，另外一个线程就可以获取资源，正常地执行了。
     */
    static Lock lock1 = new ReentrantLock();
    static Lock lock2 = new ReentrantLock();

    public static void main(String[] args) {
        Thread thread1 = new Thread(new ThreadDemo(lock1, lock2), "thread-A");
        Thread thread2 = new Thread(new ThreadDemo(lock2, lock1), "thread-B");
        thread1.start();
        thread2.start();
        // 线程中断
        thread1.interrupt();
    }

    static class ThreadDemo implements Runnable {
        Lock lock1;
        Lock lock2;

        public ThreadDemo(Lock lock1, Lock lock2) {
            this.lock1 = lock1;
            this.lock2 = lock2;
        }

        @Override
        public void run() {
            try {
                lock1.lockInterruptibly();
                log.info("获取锁: {}", Thread.currentThread().getName());
                TimeUnit.MILLISECONDS.sleep(50);
                lock2.lockInterruptibly();
                log.info("获取锁: {}", Thread.currentThread().getName());
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                log.info("释放锁: {}", "lock1");
                lock1.unlock();
                log.info("释放锁: {}", "lock2");
                lock2.unlock();
                log.info("获取到资源，正常结束");
            }
        }
    }
}
